#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : sse_route.py
@TIME          : 2025/03/03 10:00:00
@AUTHOR        : chenlip
@VERSION       : 0.1.0
@DESCRIPTION   : 用户路由SSE消息发布
                简化版本：仅使用user_id作为通道标识，不验证登录状态
'''

from flask import Blueprint, g, request, Response
from flask import current_app, jsonify
from init_app import cache
from app.middlewares.error_handler import route_exceptions
from app.middlewares.sse import MemorySSE

import hashlib
import hmac
import time
import json
from app.models.user import User

sse_bp = Blueprint('sse', __name__, url_prefix='/sse')

@sse_bp.route('/stream', methods=['GET'])
@route_exceptions
def sse_stream():
    """SSE事件流端点"""
    channel = request.args.get('channel', 'global')
    user_id = request.args.get('user_id', 0)
    timestamp = int(request.args.get('timestamp', 0))
    signature = request.args.get('signature')
    
    # 验证用户通道
    if channel.startswith('user.'):

        # 检查是否有该用户
        _user_id = User.query.get(user_id)
        if not _user_id:
            current_app.logger.warning(f"SSE事件流端点, 找不到指定的用户ID: {user_id}")
            return _sse_error_response("SSE事件流端点, 找不到指定的用户ID", 400)
        
        try:
            
            # 验证时间戳（例如5分钟内有效）
            current_time = int(time.time() * 1000)
            time_diff = abs(current_time - timestamp)
            if time_diff > 5 * 60 * 1000:  # 5分钟
                return _sse_error_response("无效的时间戳", 403)
                
            # 验证签名
            _vu = user_id + '_' + signature
            valid = _verify_signature(_vu)
            if not valid:
                current_app.logger.warning(f"无效的签名: {channel}")
                return _sse_error_response("无效的签名", 403)
            
            # 简化用户通道名称，保持用户通道
            channel = f'user.{user_id}'
            
        except (ValueError, IndexError) as e:
            current_app.logger.error(f"解析通道失败: {str(e)}")
            return _sse_error_response("无用的通道参数", 400)
    
    current_app.logger.info(f"用户ID {user_id if user_id else 'anonymous'} 订阅通道: {channel}")
    
    # 返回SSE流
    return MemorySSE.stream(channel)

@sse_bp.route('/gensignature', methods=['GET'])
@route_exceptions
def generate_signature_route():
    """生成SSE连接签名的路由, 供前端调用"""
    user_id = request.args.get('user_id')
    timestamp = int(time.time() * 1000)
    secret_key = current_app.config.get('SSE_SIGNATURE_KEY', 'default_key')
    message = f"{user_id}:{timestamp}:{secret_key}"

    signature = hashlib.sha256(message.encode()).hexdigest()
    # 保存到缓存，以便后续验证
    _vu = user_id + '_' + signature
    cache.set(_vu, timestamp, timeout=5*60)  # 5分钟有效

    return jsonify({
        "signature": signature,
        "timestamp": timestamp,  # 返回服务器生成的时间戳
        "expires_in": 300  # 5分钟有效期(秒)
    })


def _verify_signature(signature_key):
    """验证SSE连接签名"""
    try:
        # signature_key格式为 user_id_signature
        timestamp = cache.get(signature_key)
        if not timestamp:
            current_app.logger.error("未找到或已过期的签名密钥")
            return False
        
        # 验证成功 - 时间戳存在且未过期(缓存自动处理过期)
        return True
        
    except Exception as e:
        current_app.logger.error(f"验证签名时出错: {str(e)}")
        return False

def _sse_error_response(message, code):
    """返回SSE格式的错误响应"""
    error_data = {"message": message, "code": code}
    return Response(
        f"event: error\ndata: {json.dumps(error_data)}\n\n",
        mimetype="text/event-stream",
        headers={
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'X-Accel-Buffering': 'no' # NGINX禁用缓冲
        }
    )